package org.zgy.stock.threads;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.zgy.stock.dto.StockPriceDto;
import org.zgy.stock.model.StockPrice;
import org.zgy.stock.service.StockPriceService;
import org.zgy.stock.utils.okhttp3.OkHttpUtil;

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

public class StockPriceThread implements Runnable{
    private final static String API = "https://push2his.eastmoney.com/api/qt/stock/kline/get?fields1=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13&fields2=f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61&beg=0&end=20500101&ut=fa5fd1943c7b386f172d6893dbfba10b&rtntype=6&klt=101&fqt=1";
    private final String code;
    private final StockPriceService stockPriceService;

    public StockPriceThread(String code, StockPriceService stockPriceService) {
        this.code  = code;
        this.stockPriceService = stockPriceService;
    }

    @Override
    public void run() {
        Instant start = Instant.now();
        String secid = "";
        if (code.startsWith("6")) {
            secid = "1." + code;
        }else {
            secid = "0." +code;
        }
        String url = API + "&secid=" + secid;
        String result = OkHttpUtil.getRequest(url, null);
        JSONObject json = JSON.parseObject(result);
        JSONObject data_json = json.getJSONObject("data");
        String name = data_json.getString("name");
        List<String> lkines = data_json.getObject("klines", List.class);
        System.out.println("the size is: " + lkines.size());
        parallelStreamWithoutLock(name, lkines);
        Instant end = Instant.now();
        System.out.println("<UNK>" + Duration.between(start, end).toMillis() + "ms");
    }

    /**
     * 基于parallelStream进行实现，不加锁
     * @param name
     * @param lkines
     *
     * 15250ms —— 数据不对
     */
    private void parallelStreamWithoutLock(String name, List<String> lkines) {
        ConcurrentLinkedDeque<StockPrice> queue = new ConcurrentLinkedDeque<>();
        List<StockPrice> list = lkines.parallelStream().map(item -> {
            String[] items = item.split(",");
            StockPrice stockPrice = new StockPrice();
            stockPrice.setStockCode(code);
            stockPrice.setStockName(name);
            stockPrice.setStockDate(LocalDate.parse(items[0], DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            stockPrice.setOpenPrice(Double.parseDouble(items[1]));
            stockPrice.setClosePrice(Double.parseDouble(items[2]));
            stockPrice.setMaxPrice(Double.parseDouble(items[3]));
            stockPrice.setMinPrice(Double.parseDouble(items[4]));
            stockPrice.setVolume(Integer.parseInt(items[5]));
            stockPrice.setCje(Double.parseDouble(items[6]));
            stockPrice.setZdf(Double.parseDouble(items[8]));
            stockPrice.setZf(Double.parseDouble(items[9]));
            stockPrice.setHsl(Double.parseDouble(items[10]));
            return stockPrice;

        }).toList();
        this.stockPriceService.batch_insert(list);

    }

    /**
     * 基于parallelStream和Lock进行实现的情况
     * @param name
     * @param lkines
     *
     * 119765ms
     */
    private void parallelStream(String name, List<String> lkines) {
        List<StockPriceDto> list = new ArrayList<>();
        ReentrantLock lock = new ReentrantLock();
        lkines.parallelStream().forEach(item -> {
            String[] items = item.split(",");
            StockPriceDto stockPriceDto = StockPriceDto.builder()
                    .stockCode(code)
                    .stockName(name)
                    .stockDate(LocalDate.parse(items[0], DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                    .openPrice(Double.parseDouble(items[1]))
                    .closePrice(Double.parseDouble(items[2]))
                    .maxPrice(Double.parseDouble(items[3]))
                    .minPrice(Double.parseDouble(items[4]))
                    .volume(Integer.parseInt(items[5]))
                    .cje(Double.parseDouble(items[6]))
                    .zdf(Double.parseDouble(items[8]))
                    .zf(Double.parseDouble(items[9]))
                    .hsl(Double.parseDouble(items[10]))
                    .build();

            try {
                lock.lock();
                list.add(stockPriceDto);
                if (list.size() > 50){
//                    this.stockPriceService.batch_insert(list);
                    list.clear();
                }
            }finally {
                lock.unlock();
            }


        });
//        this.stockPriceService.batch_insert(list);

    }

}
